#pragma once
#include "Timestamp.h"
#include "noncopyable.h"
#include "Logger.h"

#include <functional>
#include <memory>

class EventLoop;


class Channel : Noncopyable{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop *loop, int fd);
    ~Channel();

    // fd得到通知后，处理事件的
    void handleEvent(Timestamp receiveTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallback cb) {readCallback_ = std::move(cb);};
    void setWriteCallback(EventCallback cb) {writeCallback_ = std::move(cb);};
    void setCloseCallback(EventCallback cb) {closeCallback_ = std::move(cb);};
    void setErrorCallback(EventCallback cb) {errorCallback_ = std::move(cb);};

    // 防止当channel被手动remove掉，channel还在执行操作
    void tie(const std::shared_ptr<void>&);

    int fd() const {return fd_;}
    int events() const {return events_;}
    void set_revents(int revent) {revents_ = revent;}

    // 设置fd相应的事件状态
    void enableReading(){ events_ |= kReadEvent; update();}
    void disableReading(){events_ &= ~kReadEvent; update();}
    void enableWriting(){events_ |= kWriteEvent; update();}
    void disableWriting(){events_ &= ~kWriteEvent; update();}
    void disableAll(){events_ = kNoneEvent; update();}

    // 返回fd当前的事件状态
    bool isNonoEvent() const{return events_ == kNoneEvent;}
    bool isWriting() const{return events_ & kWriteEvent;}
    bool isReading() const{return events_ & kReadEvent;}

    int index(){return index_;}
    void set_index(int index){index_ = index;}

    EventLoop* ownerLoop(){return loop_;}
    void remove();


private:
    void update();
    void handleEventWithGuard(Timestamp receiveTime);
    
    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop * loop_; // 事件循环
    const int fd_;      // fd, Poller监听的对象
    int events_;// 注册fd感兴趣的事件。读写。。 （EPOLLIN）
    int revents_;// 就绪事件
    int index_;

    std::weak_ptr<void> tie_;
    bool tied_;

    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;


};